/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package nsip.components.ds;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import nsip.model.ProductPartInfo;
import nsip.model.ProductInfo;
import nsip.util.LazyInitializingMap;
import se.sics.tasim.props.BOMBundle;
import se.sics.tasim.props.ComponentCatalog;

/**
 *
 * @author nico
 */
public class Catalog {

    private BOMBundle bomBundle;
    private ComponentCatalog componentCatalog;

    private Map<Integer, ProductInfo> productInfoMap;
    private Map<Integer, ProductPartInfo> productPartInfoMap;

    private Map<String, Integer[]> supplierProductMap;
    
    public Catalog() {
        this.productInfoMap = new LazyInitializingMap<Integer, ProductInfo>() {
            @Override
            protected ProductInfo initialize(Object key) {
                return createProductInfo((Integer) key);
            }
        };

        this.productPartInfoMap = new LazyInitializingMap<Integer, ProductPartInfo>() {
            @Override
            protected ProductPartInfo initialize(Object key) {
                return createProductPartInfo((Integer) key);
            }            
        };
        
        this.supplierProductMap = new HashMap();
    }

    /**
     * Set component catalog
     * @param componentCatalog
     */
    public void setComponentCatalog(ComponentCatalog componentCatalog) {
        this.componentCatalog = componentCatalog;
    }

    /**
     * Set bom bundle
     * @param bomBundle
     */
    public void setBOMBundle(BOMBundle bomBundle) {
        this.bomBundle = bomBundle;
    }

    /**
     * Creates a product info for the product identified by the specified id
     * @param productID
     * @return
     */
    private ProductInfo createProductInfo(int productID) {
        int index = bomBundle.getIndexFor(productID);
        int[] componentIDs = bomBundle.getComponents(index);
        
        ProductPartInfo[] parts = new ProductPartInfo[componentIDs.length];
        for (int i = 0; i < parts.length; i++) {
            parts[i] = productPartInfoMap.get(componentIDs[i]);
        }
        
        return new ProductInfo(
            productID,
            bomBundle.getProductBasePrice(index),
            bomBundle.getProductName(index),
            bomBundle.getAssemblyCyclesRequired(index),
            parts);
    }

    private ProductPartInfo createProductPartInfo(int partID) {
        int index = componentCatalog.getIndexFor(partID);

        return new ProductPartInfo(
                partID,
                componentCatalog.getProductBasePrice(index),
                componentCatalog.getProductName(index),
                componentCatalog.getSuppliers(index));
    }
        
    /**
     * Returns the bom bundle
     * @return
     */
    public ProductInfo getInfo(int productID) {
        return productInfoMap.get(productID);
    }

    /**
     * Return suppliers for a given part
     * @param partID
     * @return
     */
    public String[] getSuppliers(int partID) {
        return productPartInfoMap.get(partID).getSuppliers();
    }

    /**
     * Returns the part info for the specified part id
     * 
     * @param partID
     * @return
     */
    public ProductPartInfo getPartInfo(int partID) {
        return productPartInfoMap.get(partID);
    }

    /**
     * Return parts supplied by certain supplier
     * 
     * @param supplier
     * 
     * @return part ids of products to be produced by the supplier
     */
    public Integer[] getPartsSuppliedBy(String supplier) {
        Integer[] parts = supplierProductMap.get(supplier);
        if (parts == null) {
            ArrayList<Integer> partsList = new ArrayList();
            for (ProductPartInfo info: productPartInfoMap.values()) {
                for (String s: info.getSuppliers()) {
                    if (s.equals(supplier)) {
                        partsList.add(info.getId());
                        break;
                    }
                }
            }

            parts = partsList.toArray(new Integer[0]);
            supplierProductMap.put(supplier, parts);
        }
        
        return parts;
    }
}
